package com.atguigu.gmall.seckill.task;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.seckill.mapper.SeckillMapper;
import com.atguigu.gmall.seckill.util.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @Author: dongdong lau
 * @CreateTime: 2021/7/14 20:59
 * @Description: 秒杀商品存入缓存
 */
@Component
public class SecKillTask {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillMapper seckillMapper;

    @Scheduled(cron = "0/15 * * * * *")
    public void seckillIntoRedisTask(){
        // 计算5个时间段的时间
        List<Date> dateMenus = DateUtil.getDateMenus();
        // 遍历5个时间段,获取起始时间到和结束时间
        for (Date dateMenu : dateMenus) {
            // 获取起始时间段
            String startTime = DateUtil.data2str(dateMenu, DateUtil.PATTERN_YYYY_MM_DDHHMM);
            // 获取结束时间段
            Date date = DateUtil.addDateHour(dateMenu, 2);
            String endTime = DateUtil.data2str(date, DateUtil.PATTERN_YYYY_MM_DDHHMM);
            // 构建查询条件
            LambdaQueryWrapper<SeckillGoods> wrapper = new LambdaQueryWrapper<>();
            // 组装查询条件(审核查询条件) status为1审核通过
            wrapper.eq(SeckillGoods::getStatus,"1");
            // 库存大于零
            wrapper.gt(SeckillGoods::getStockCount,0);
            // （起始时间 =< now < 起始时间+2hours）在范围内
            wrapper.ge(SeckillGoods::getStartTime,startTime);
            wrapper.le(SeckillGoods::getEndTime,endTime);
            // redis中没有这个数据
            // 设置存入redis中的key
            String key = DateUtil.data2str(dateMenu, DateUtil.PATTERN_YYYYMMDDHH);
            Set keys = redisTemplate.boundHashOps("SeckillGoods_" + key).keys();
            if(keys != null && keys.size() > 0){
                wrapper.notIn(SeckillGoods::getId,keys);
            }
            // 将没有结束秒杀的商品存入数据库
            List<SeckillGoods> seckillGoods = seckillMapper.selectList(wrapper);
            for (SeckillGoods seckillGood : seckillGoods) {
                // 将符合查询条件的数据存入Redis
                redisTemplate.boundHashOps("SeckillGoods_"+ key).put(seckillGood.getId() + "",seckillGood);
                // 获取商品库存数量
                Integer stockCount = seckillGood.getStockCount();
                // 构建一个数量长度的数组
                String[] ids = getSeckillGoodsQueue(JSONObject.toJSONString(seckillGood.getId()), stockCount);
                // 将数组中每个元素存储到队列中
                redisTemplate.boundListOps("SeckillGoodsQueue_" + seckillGood.getId()).leftPushAll(ids);
                // 记录库存
                redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(seckillGood.getId(),stockCount);
            }
        }
    }

    /**
     *
     * 构建商品库存个数长度的数组
     * @param goodsId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String goodsId, Integer stockCount){
        // 构建一个库存长度的数组
        String[] ids = new String[stockCount];
        for (int i = 0; i < stockCount; i++) {
            ids[i] = goodsId;
        }
        // 返回数据
        return ids;
    }

}
